pub mod skippable;
pub mod wd;
pub mod fhd;
pub mod zstd;
pub mod error;

pub use skippable::*;
pub use zstd::*;
pub use error::*;
use crate::{byte::*, workspace::{WorkSpace, OutputWorkSpace}};

#[derive(Debug)]
pub enum Frame {
    Zstd(ZstdFrame),
    Skippable(SkippableFrame),
}

impl Frame {
    pub fn serialize_into<W:ByteWrite>(&self,writer:&mut ByteWriter<W>) -> FrameResult<()> {
        match self {
            Self::Zstd(frame) => {
                writer.write_from_u32(ZSTD_FRAME_MAGIC)?;
                frame.serialize_into(writer)
            }
            Self::Skippable(frame) => {
                writer.write_from_u32(SKIP_FRAME_MAGIC_RANGE.start)?;
                frame.serialize_into(writer)
            }
        }
    }

    pub fn deserialize_from<R:ByteRead>(reader:&mut ByteReader<R>) -> FrameResult<Self> {
        let magic:u32 = reader.read_to_u32()?;
        let mut work_space = WorkSpace::new();
        if magic == ZSTD_FRAME_MAGIC {
            return Ok(Self::Zstd(ZstdFrame::deserialize_from(reader,&mut work_space)?));
        } else if SKIP_FRAME_MAGIC_RANGE.contains(&magic) {
            return Ok(Self::Skippable(SkippableFrame::deserialize_from(reader)?));
        } else {
            return Err(FrameError::UnknownMagic(magic));
        }   
    }

    pub fn uncompressed_to<O:OutputStream>(&self, output:&mut O, workspace:&mut OutputWorkSpace) -> OutputResult<usize>  {
        match self {
            Self::Skippable(_) => Ok(0),
            Self::Zstd(zstd) => zstd.uncompressed_to(output, workspace),
        }
    }
}